fix(cli): error messages in utils/ misc (flags, fs, git, npm, promise, terminal)#1260
Merged
John-David Dalton (jdalton) merged 3 commits intomainfrom Apr 24, 2026
Merged
Conversation
… strategy Final PR in the error-message series. Covers everything not already touched by #1255-#1259: utils/basics, utils/config, utils/fs, utils/git, utils/npm, utils/promise, utils/terminal, and the flags module at the root of the CLI tree. Sources: - flags.mts: 2 throws (--max-old-space-size, --max-semi-space-size) — name the flag, show the offending value, suggest a concrete megabyte value. - utils/config.mts: 1 throw (SOCKET_CLI_CONFIG base64 decode) — explains the replacement-character symptom and how to re-encode. - utils/basics/vfs-extract.mts: 4 throws (SEA VFS extraction for Python + security tools) — name the missing paths, the exit codes, and point at the "rebuild the SEA binary" fix. - utils/promise/queue.mts: 1 throw (PromiseQueue concurrency guard) — show the offending value and suggest 4/8. - utils/npm/spec.mts: 1 throw (PURL conversion) — show the input, state what a valid npm spec looks like. - utils/git/operations.mts: 1 throw (git-not-on-PATH) — point at install and the local-path env-var override. - utils/git/gitlab-provider.mts: 2 throws (no token, PR creation after retries) — name the token scope, the retry count, the repo/head refs. - utils/fs/path-resolve.mts: 1 throw (npm path-walk iteration cap) — name the start path, current directory, and what usually causes the cycle (symlinks). - utils/terminal/iocraft.mts: 1 throw (native-module load failure) — show the underlying error and the offending platform/arch triple. Skipped (already informative): - github-provider.mts pass-through errors (forward inner CResult cause/message) - gitlab-provider.mts try/catch wrappers that call formatErrorWithDetail (inner error has context) - 'process.exit called' sentinel throws in npm/pnpm/yarn/with- subcommands paths (test harness re-raise markers, not user-facing) Tests updated: - test/unit/utils/promise/queue.test.mts (2 assertions) - test/unit/utils/npm/spec.test.mts (2 assertions) - test/unit/utils/git/gitlab-provider.test.mts (3 assertions) Full suite (343 files / 5225 tests) passes. Completes the series: #1255 (commands/) → #1256 (utils/dlx/) → #1257 (utils/update + utils/command/) → #1258 (env/ + constants/) → #1259 (test/) → this.
Four issues flagged by Cursor bugbot on #1260: 1. (Medium) gitlab-provider.mts: error said 'check GL_TOKEN permissions' but the actual env var is GITLAB_TOKEN (as the same file's getGitLabToken confirms). Fixed to GITLAB_TOKEN. 2. (Medium) git/operations.mts: error suggested 'set SOCKET_CLI_GIT_PATH to point at a specific binary' — that env var is not read anywhere. Removed the false suggestion; kept the real fix (install git and put it on PATH) with package-manager examples. 3. (Low) terminal/iocraft.mts: '(e as Error).message' evaluates to undefined when a non-Error is thrown. Switched to 'e instanceof Error ? e.message : String(e)' for safe stringification. 4. (Low) gitlab-provider.mts: error said 'after ${retries} retries' but the loop runs attempt 1..retries inclusive — retries is the total attempt count, not retries beyond the first. Reworded to 'attempts'. Matching test assertions updated. Caught by #1260 bugbot review.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 22, 2026
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 22, 2026
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 22, 2026
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 22, 2026
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
- basics/vfs-extract.mts: missingTools list now renders as prose
via joinAnd('a, b, and c').
- terminal/iocraft.mts: inline `e instanceof Error ? e.message :
String(e)` swapped for getErrorCause(e). require() of a native
binding can throw non-Error values, so the safe-stringify with
UNKNOWN_ERROR fallback is correct here.
No behavior change for Error throws.
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
2d9bec8 to
579638d
Compare
Contributor
Author
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 579638d. Configure here.
James Tu (jmsjtu)
approved these changes
Apr 24, 2026
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 24, 2026
* fix(cli): align test/ error messages with 4-ingredient strategy
Rewrites the Socket-JSON contract validator and auth-flow mocks under
packages/cli/src/test/ and packages/cli/test/ to follow the What /
Where / Saw vs. wanted / Fix strategy from CLAUDE.md.
Sources:
- src/test/json-output-validation.mts (6 throws): each violation now
spells out the full Socket-JSON contract, the received value, and
a concrete fix ("add ok:true", "return empty object", etc.).
Long output payloads are truncated to 200 chars in the message so
errors stay readable.
- src/test/mocks/socket-auth.mts (2 throws): "Authentication failed"
and "OAuth timeout" now call out that they come from a test
fixture and point at the configuration flag to change.
- test/json-output-validation.mts (2 non-throwing returns): message
values now include the exit code / parse error and a stdout
preview so failing tests diagnose themselves.
- test/smoke.sh (6 labels): updated to mirror the TS validator so
the bash and JS harnesses produce the same wording.
Tests: full suite (343 files / 5225 tests) still passes. No
assertions touched — the unrelated "Authentication failed" hits
in other tests are test fixtures constructing their own Errors,
not references to the mock.
Follows strategy from #1254. Continues #1255-#1258.
* chore(cli): harden (e as Error) casts to safe stringify
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'.
Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
This was referenced Apr 24, 2026
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 24, 2026
) * fix(cli): align commands/ error messages with 4-ingredient strategy Rewrites error messages across packages/cli/src/commands/ to follow the What / Where / Saw vs. wanted / Fix strategy from CLAUDE.md's new Error Messages section. Sources: - scan/cmd-scan-create.mts: 5 throws (ecosystems + 4 numeric flags) - scan/cmd-scan-reach.mts: 4 throws (ecosystems + 3 numeric flags) - scan/cmd-scan-list.mts: 2 throws (--page, --per-page) - organization/cmd-organization-dependencies.mts: 2 throws (--limit, --offset) - audit-log/cmd-audit-log.mts: 2 throws (--page, --per-page) - threat-feed/cmd-threat-feed.mts: 1 throw (--per-page) - fix/cmd-fix.mts: 1 logger.fail (--ecosystems) - ask/cmd-ask.mts: 1 InputError (missing QUERY) - login/cmd-login.mts: 1 InputError (non-interactive TTY) - wrapper/add-socket-wrapper.mts: 1 throw (fs.appendFile failure) - wrapper/postinstall-wrapper.mts: 1 throw (nested wrapper setup) - manifest/convert-gradle-to-maven.mts: 1 throw (spawn returned no output) - fix/coana-fix.mts: 1 throw (coana returned non-array JSON) - config/handle-config-set.mts: 1 throw (missing VALUE) Tests updated to match new substrings (regex patterns for easier future evolution). All throws previously typed as plain Error that represent user input validation have been converted to InputError, following the codebase convention. Follows strategy landed in #1254. * chore(cli): harden (e as Error) casts to safe stringify Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR. * chore(cli): use getErrorCause helper in add-socket-wrapper Switch the inline `e instanceof Error ? e.message : String(e)` to getErrorCause(e), matching the fleet helper pattern. Same behavior for Error throws; non-Error throws now produce 'Unknown error' instead of '[object Object]'. * fix(cli): wrap wrapper fs.appendFile failures as FileSystemError Cursor bugbot flagged both add-socket-wrapper.mts and postinstall-wrapper.mts for rendering I/O errors with the "Invalid input" title and "Check command syntax with --help" recovery hint (InputError's display mapping). fs.appendFile failures are permission / disk / path problems — FileSystemError renders them as "File system error" with contextual recovery (check file permissions, disk space, etc.). Pass the file path (where available) and the ErrnoException code through so FileSystemError can surface EACCES/ENOSPC/ENOENT-specific recovery text. Reported on PR #1255. * test(cli): update postinstall-wrapper mock to export FileSystemError The previous commit swapped InputError → FileSystemError in postinstall-wrapper.mts but left the test's vi.mock factory still exporting InputError, so the source couldn't resolve its FileSystemError import under vitest: [vitest] No "FileSystemError" export is defined on the ".../src/utils/error/errors.mts" mock Replace the mock's InputError stub with a FileSystemError stub that matches the real class's shape (path, code, recovery) so the source code resolves correctly. The existing regex assertion on the error message is unaffected. * fix(cli): address bugbot re-review findings on #1255 Two issues flagged on the fresh review of HEAD: - FileSystemError duplicates the filepath: the message embeds ${file} AND the constructor receives `file` as the path argument. Since display.formatErrorForDisplay appends \`(\${error.path})\` automatically, this surfaced the path twice. Drop the \${file} interpolation from the message — the path arg alone is enough. - Scan command numeric flag errors overstated validation: \`--pull-request\` claimed "non-negative integer" and \`--reach-concurrency\` claimed "positive integer," but the checks only rejected NaN. Negatives and floats passed through silently. Tighten the validation to match what the error messages promise — Number.isInteger + range check at every call site (cmd-scan-create.mts for both flags, cmd-scan-reach.mts for reach-concurrency). The third flagged item (FileSystemError vs InputError in the wrapper commands) was cursor re-flagging a finding already addressed in commit 769170f — the current code already uses FileSystemError. No action. * test(cli): update add-socket-wrapper regex for new FileSystemError shape Previous commit (2269113) dropped the \${file} interpolation from FileSystemError's message to avoid display.formatErrorForDisplay double-printing the path (which it appends from error.path). The test regex still matched the pre-change format — /failed to append socket aliases to \/etc\/protected-file/ — and wouldn't have matched the new message. Assert on the new shape instead: - regex matches `failed to append socket aliases (Permission denied)` - toMatchObject pins name='FileSystemError' and path='/etc/protected-file' Drive-by: the existing regex had \./etc\/protected-file/ but the message never contained that substring after the FileSystemError swap — so the assertion was silently wrong. Flagged by cursor on #1255.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 24, 2026
* fix(cli): align utils/dlx/ error messages with 4-ingredient strategy
Rewrites error messages across packages/cli/src/utils/dlx/ to follow
the What / Where / Saw vs. wanted / Fix strategy from CLAUDE.md.
Sources:
- spawn.mts: 27 messages
- 6x 'Unexpected resolution type for <tool>' — now name the resolver
function and the actual resolution.type seen
- Archive/platform errors name the supported formats/platforms
- Python DLX errors surface the lock file path and cache dir
- PyPI fetch errors include the URL that failed
- Security errors (zip-slip, symlink escape) tell user to delete
the cached asset and report upstream
- resolve-binary.mts: 4 messages (socket-patch, trivy, trufflehog,
opengrep platform support) — each now lists supported platforms
and suggests how to install the tool manually
- vfs-extract.mts: 5 messages (SEA VFS extraction failures) — each
names what went wrong with the bundle and how to recover
(usually: rebuild SEA)
Internal invariant errors stay as plain Error (not InputError) but
are informative enough that if they ever fire, the user can open
a useful bug report.
Tests updated: test/unit/utils/dlx/resolve-binary.test.mts (1
substring match switched to regex).
Follows strategy from #1254. Part of the multi-PR series started
by #1255 (commands/).
* fix(cli): hoist lockFile/pythonDir above retry check in ensurePythonDlx
The previous commit referenced `${lockFile}` and `${pythonDir}` in
the MAX_RETRIES error message, but those consts were declared AFTER
the retry check. Hitting the retry path threw ReferenceError from
the temporal dead zone instead of the intended InputError.
Fix: move the three const declarations (pythonDir, pythonBin,
lockFile) above the MAX_RETRIES guard. Caught by Cursor bugbot
(#1256 (comment))
and confirmed by the type-check job.
* chore(cli): harden (e as Error) casts to safe stringify
Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'.
Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR.
* chore(cli): use joinAnd + getErrorCause helpers in dlx error messages
Switch to shared fleet helpers so error lists render as human prose
('a, b, and c') and error-cause stringification works safely for
non-Error throws (falls back to 'Unknown error' instead of crashing
or producing 'undefined').
- resolve-binary.mts: SOCKET_PATCH_ASSETS + OPENGREP_ASSETS
platform lists now use `joinAnd(Object.keys(...))`.
- vfs-extract.mts: missingTools list uses joinAnd; extract-failure
error now uses getErrorCause(e) — equivalent to the inline
'e instanceof Error ? e.message : String(e)' with the standard
UNKNOWN_ERROR fallback.
- spawn.mts: output-map listing uses joinAnd.
No behavior change for Error throws; non-Error throws now produce
'Unknown error' instead of '[object Object]' or similar.
John-David Dalton (jdalton)
added a commit
that referenced
this pull request
Apr 24, 2026
) * fix(cli): align env/ + constants/ + build-script error messages with 4-ingredient strategy Rewrites runtime and build-time error messages for the build-inlined version/checksum pipeline to follow the What / Where / Saw vs. wanted / Fix strategy from CLAUDE.md. Sources (runtime): - env/coana-version.mts, env/sfw-version.mts (2 getters), env/socket-basics-version.mts, env/socket-patch-version.mts, env/trufflehog-version.mts, env/trivy-version.mts, env/opengrep-version.mts, env/pycli-version.mts — 9 "INLINED_X not found" errors. Each now names the exact env var, the bundle-tools.json path it comes from, and how to rebuild (`pnpm run build:cli`). - env/checksum-utils.mts — parseChecksums() and requireChecksum() now show the exact JSON.parse error or the list of known assets so you can see what was in vs. out of the map. - constants/paths.mts — getSocketRegistryPath() now enumerates every env var the app-data lookup checks (HOME, USERPROFILE, LOCALAPPDATA, XDG_DATA_HOME) so a cold environment tells you which to set. Sources (build-time scripts, same message style for consistency): - scripts/sea-build-utils/downloads.mts — 3 checksum-missing errors in the SEA build path, each now names the bundle-tools.json key and tells you to run `pnpm run sync-checksums`. No tests pinned these messages (only dist/cli.js — unchecked-in build output). Follows strategy from #1254. Continues #1255, #1256, #1257. * chore(cli): harden (e as Error) casts to safe stringify Switch `(e as Error).message` to `e instanceof Error ? e.message : String(e)` so that when a non-Error value is thrown (strings, objects, null) the error message stays informative instead of becoming 'undefined'. Same fix as applied to #1260 (iocraft.mts) after Cursor bugbot flagged the pattern on that PR. * fix(cli): address Cursor bugbot findings on checksum error messages Two issues flagged by Cursor bugbot on #1258: 1. (Low) parseChecksums() built the env var name as `INLINED_${toolName.toUpperCase()}_CHECKSUMS`. When toolName has spaces (e.g. 'Socket Patch'), toUpperCase() produces 'SOCKET PATCH' → 'INLINED_SOCKET PATCH_CHECKSUMS' — not a valid env var name. The real env var is INLINED_SOCKET_PATCH_CHECKSUMS. 2. (Low) Both parseChecksums() and requireChecksum() embedded `tools.${toolName}.checksums` to reference bundle-tools.json paths, but toolName is the display name (PyCLI, OpenGrep, Socket Patch) not the case-sensitive JSON key (socketsecurity, opengrep, socket-patch). Both came from the same root cause: I treated the display-name parameter as if it were a canonical identifier. Fix: reword the messages to just name the tool in prose ('inlined checksums for X', 'X has no SHA-256 for Y') and point at the 'matching entry in bundle-tools.json' instead of inventing a wrong path. Keeps the 4-ingredient structure (what/where/saw/fix) without claiming identifiers that don't exist. Caught by #1258 bugbot review. * chore(cli): use joinAnd from @socketsecurity/lib/arrays for error lists Switch the 4 `Object.keys(x).join(', ')` calls in error messages on this branch to `joinAnd(Object.keys(x))` so they render as human prose (e.g. 'a, b, and c') instead of machine-y comma-joins. Sites: - src/env/checksum-utils.mts: requireChecksum known-assets list - scripts/sea-build-utils/downloads.mts: 3 missing-checksum errors (external tools, socketsecurity wheel, socket-basics archive) No behavior change — just uses the fleet helper consistently. * fix(cli): use bracket notation for hyphenated tool keys in error message Cursor flagged the checksum-missing error in downloads.mts: it used \`tools.\${toolName}.checksums\` (dot notation) which produces an invalid JSONPath like \`tools.socket-patch.checksums\` when toolName is hyphenated. The socket-basics site a few hundred lines down already uses bracket notation for the same reason; make this one match. Reported on PR #1258.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Align error messages across the miscellaneous
utils/subtrees that didn't fit the other batches, with the 4-ingredient strategy from CLAUDE.md (#1254).Scope
packages/cli/src/flags.mtspackages/cli/src/utils/basics/vfs-extract.mtspackages/cli/src/utils/config.mtspackages/cli/src/utils/fs/path-resolve.mtspackages/cli/src/utils/git/gitlab-provider.mts,git/operations.mtspackages/cli/src/utils/npm/spec.mtspackages/cli/src/utils/promise/queue.mtspackages/cli/src/utils/terminal/iocraft.mtsPlus matching unit-test updates for
git/gitlab-provider,npm/spec,promise/queue.Bugbot fixes included:
Related PRs (sibling error-message batches)
commands/*(14 files)utils/dlx/*utils/update/+utils/command/+ error library migration + CLAUDE.md doctrine (supersedes docs(claude): align Error Messages with fleet doctrine #1261)env/+constants/+ sea-build scriptsTest plan